package com.fengkong.analysis.simple;

import org.junit.Test;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 核心代码中，解析流程处理
 * todo 测试使用
 *
 * @Author longdeng
 * @Date 2020/7/28 0028 23:29
 */
public class AnalyisTest {


    /**
     * 定义一段数据，比对解析过程
     * 比如我有4个数据
     * a，b，c，d
     * a可以直接解析
     * b可以需要c解析后的数据
     * c可以直接解析
     * d需要b和c的数据
     * <p>
     * 解析过程中，可能会遇到空值，建议使用特定的字符串进行处理，以便于处理后续的逻辑处理提供方便
     */
    @Test
    public void dataAnalyisTest() {
        // 构建测试数据
        List<Map<String, Object>> dataArray = createDataTest();
        int index = dataArray.size();
        List<Map<String, Object>> dataAnalyisArray = new ArrayList<>();
        boolean flag = false;
        while (index > 0) {
            for (int i = 0; i < dataArray.size(); i++) {
                Map<String, Object> m = dataArray.get(i);
                String dataFlag = AnalyisUtil.emptyString(m.get("dataFlag"));
                if (Objects.isNull(dataFlag) || "0".equals(dataFlag)) {   // 标识当前数据没有被解析过,或者解析失败了
                    // 解析数据
                    // 入参，当前对象信息，解析后数据对象信息
                    Map<String, Object> resultMap = dataAnalyis(m, dataAnalyisArray);
                    String code = AnalyisUtil.emptyString(resultMap.get("code"));
                    if ("200".equals(code)) {    // 解析成功了
                        flag = true;
                        index--;
                    }
                }
            }
            if (!flag) {
                // 构建错误提示信息
                dataAnalyisErrorInfo(dataArray);
                break;
            }
            flag = false;
        }
        System.out.println(dataAnalyisArray);
    }


    /**
     * 构建数据解析过程错误信息
     *
     * @param dataArray
     */
    public void dataAnalyisErrorInfo(List<Map<String, Object>> dataArray) {

        for (Map<String, Object> m : dataArray) {
            String dataName = AnalyisUtil.emptyString(m.get("dataName"));
            String data = AnalyisUtil.emptyString(m.get("data"));
            String dataFlag = AnalyisUtil.emptyString(m.get("dataFlag"));

            if (Objects.isNull(dataFlag) || "0".equals(dataFlag)) {
                System.out.println("当前[" + dataName + "]的表达式无法解析:" + data + ",请仔细核对该指标信息");
            }

        }

    }

    public Map<String, Object> dataAnalyis(Map<String, Object> dataMap, List<Map<String, Object>> dataAnalyisArray) {
        Map<String, Object> resultMap = new HashMap<>();
        String dataName = AnalyisUtil.emptyString(dataMap.get("dataName"));
        String data = AnalyisUtil.emptyString(dataMap.get("data"));
        String dataType = AnalyisUtil.emptyString(dataMap.get("dataType"));
        if ("1".equals(dataType)) {  // 当前数据可以直接被解析
            dataMap.put("dataFlag", "1");
            dataAnalyisArray.add(dataMap);
            resultMap.put("code", "200");
        } else if ("2".equals(dataType)) { // 当前数据需要转换解析

            // 校验#的个数，如果是奇数，那么解析要求必须失败
            int count = AnalyisUtil.stringCount(data, "#");
            if (count % 2 != 0) {
                resultMap.put("code", "400");    // 返回无法解析的标识处理
                dataMap.put("dataFlag", "0");    // 标识当前数据无法解析
                return resultMap;
            }
            String patternStr = "(#[\\w\\W]{1,}?#)";
            Pattern pattern = Pattern.compile(patternStr);
            Matcher matcher = pattern.matcher(data);
            String tempStr = data;
            while (matcher.find()) {
                String groupStr = matcher.group();
                String realDataName = groupStr.replace("#", "");
                Map<String, Object> dataMap1 = findDataMap(realDataName, dataAnalyisArray);
                if (Objects.isNull(dataMap1)) {
                    resultMap.put("code", "400");    // 返回无法解析的标识处理
                    dataMap.put("dataFlag", "0");    // 标识当前数据无法解析
                    break;
                } else {
                    String data1 = AnalyisUtil.emptyString(dataMap1.get("data"));
                    tempStr = tempStr.replace(groupStr, data1);
                    dataMap.put("dataFlag", "1");
                    resultMap.put("code", "200");
                }
            }
            // 替换已经可以转换的数据信息
            dataMap.put("data", tempStr);
            String code = AnalyisUtil.emptyString(resultMap.get("code"));
            if ("200".equals(code)) {
                dataAnalyisArray.add(dataMap);
            }
        }

        return resultMap;
    }

    /**
     * 通过dataName在List中查询已经解析的数据信息
     *
     * @param dataName         数据名称
     * @param dataAnalyisArray 已经解析的数据集合
     * @return
     */
    public Map<String, Object> findDataMap(String dataName, List<Map<String, Object>> dataAnalyisArray) {
        if (Objects.isNull(dataName) || "".equals(dataName)) {
            return null;
        }
        if (Objects.isNull(dataAnalyisArray) || dataAnalyisArray.size() == 0) {
            return null;
        }
        for (Map<String, Object> map : dataAnalyisArray) {
            String name = AnalyisUtil.emptyString(map.get("dataName"));
            if (dataName.equals(name)) {
                return map;
            }
        }
        return null;
    }

    /**
     * 构建测试数据，主要为上面说的流程进行测试处理
     *
     * @return
     */
    public List<Map<String, Object>> createDataTest() {

        List<Map<String, Object>> mapList = new ArrayList<>();
        String[] dataName = {"a", "b", "c", "d", "e"};
        String[] data = {"100", "#c#", "300", "#b#+#c#", "#e##"};
        String[] dataType = {"1", "2", "1", "2", "2"};

        for (int i = 0; i < dataName.length; i++) {
            Map<String, Object> m = new HashMap<>();
            m.put("dataName", dataName[i]);
            m.put("data", data[i]);
            m.put("dataType", dataType[i]);
            mapList.add(m);
        }
        return mapList;
    }


    @Test
    public void stringSubstringTest() {
        String source = "#a##b#|#c#";
        String target = "#";
        int count = 0;
        int start = 0;
        while (source.indexOf(target, start) >= 0 && start < source.length()) {
            count++;
            start = source.indexOf(target, start) + target.length();
        }
        System.out.println(count);
    }

}
